package com.luoluo.search;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.BooleanClause.Occur;

import com.luoluo.action.BaseAction;
import com.luoluo.bean.Document;
import com.luoluo.lucene.IndexHolder;
import com.luoluo.lucene.SearchHelper;
import com.luoluo.lucene.Searchable;

public class SearchTools {
	private final static Log log = LogFactory.getLog(SearchTools.class);
	private final static String _g_lucene_path = BaseAction.getLoadPath()
			+ "WEB-INF" + File.separator + "lucene" + File.separator;

	private final static IndexHolder g_holder;
	private final static List<Class<? extends Searchable>> classes = new ArrayList<Class<? extends Searchable>>() {
		{
			add(Document.class);
		}
	};

	static {
		try {
			g_holder = IndexHolder.init(_g_lucene_path);
		} catch (IOException e) {
			throw new RuntimeException("Unabled to init index repository.", e);
		}
	}

	public static IndexHolder getHolder() {
		return g_holder;
	}

	/**
	 * 搜索关键字
	 * 
	 * @author Winter Lau
	 * @date 2013-1-23 上午11:39:32
	 */
	public static class Keyword {
		private String name;
		private String desc;
		private String words;

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getDesc() {
			return desc;
		}

		public void setDesc(String desc) {
			this.desc = desc;
		}

		public String getWords() {
			return words;
		}

		public void setWords(String words) {
			this.words = words;
		}

		public List<String> words() {
			return Arrays.asList(StringUtils.split(words, ','));
		}
	}

	public static class Keywords {
		List<Keyword> keywords = new ArrayList<Keyword>();

		public void add(Keyword kw) {
			keywords.add(kw);
		}

		public List<Keyword> keywords() {
			return this.keywords;
		}

		public Keyword get(String name) {
			for (Keyword kw : keywords) {
				if (StringUtils.equalsIgnoreCase(kw.getName(), name))
					return kw;
				for (String w : kw.words())
					if (StringUtils.equalsIgnoreCase(w, name))
						return kw;
			}
			return null;
		}
	}

	public final static String SF_TITLE = "title";
	public final static String SF_CONTENT = "content";
	public final static String SF_ISBN = "isbn";
	public final static String SF_PUBLISH = "publish";
	public final static String SF_AUTHOR = "author";
	public final static String SF_PUBLISH_TIME = "publish_time";
	public final static String SF_ID = SearchHelper.FN_ID;

	public static List<Long> findDocument(String key, boolean onlyTitle,
			int page, int count) {
		try {
			Sort sort = new Sort(new SortField[] {
					new SortField(SF_TITLE, SortField.Type.SCORE),
					new SortField(SF_CONTENT, SortField.Type.SCORE),
					new SortField(SF_ID, SortField.Type.LONG, true) });
			return g_holder.find(Document.class, queryDocument(key, onlyTitle),
					null, sort, page, count);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Query queryDocument(String key, boolean onlyTitle) {
		key = QueryParser.escape(SearchHelper.cleanupKey(key));

		BooleanQuery query = new BooleanQuery();
		BooleanQuery complex = new BooleanQuery();
		complex.add(SearchHelper.makeQuery(SF_TITLE, key, 50.0f), Occur.SHOULD);
		if (!onlyTitle) {
			complex.add(SearchHelper.makeQuery(SF_CONTENT, key, 30.0f),
					Occur.SHOULD);
			complex.add(SearchHelper.makeQuery(SF_PUBLISH, key, 10.0f),
					Occur.SHOULD);
			complex.add(SearchHelper.makeQuery(SF_AUTHOR, key, 10.0f),
					Occur.SHOULD);
			complex.add(SearchHelper.makeQuery(SF_ISBN, key, 1.0f),
					Occur.SHOULD);
			complex.add(SearchHelper.makeQuery(SF_PUBLISH_TIME, key, 1.0f),
					Occur.SHOULD);

		}
		query.add(complex, Occur.MUST);
		return query;
	}

	public static int add(Document doc) {
		try {
			return g_holder.add(Arrays.asList(doc));
		} catch (IOException e) {
			return -1;
		}
	}

	public static void update(Document doc) {
		try {
			g_holder.update(Arrays.asList(doc));
		} catch (IOException e) {
		}
	}

	public static int delete(Document doc) {
		try {
			return g_holder.delete(Arrays.asList(doc));
		} catch (IOException e) {
			return -1;
		}
	}
}
